package com.test2{
	/**
	 * 创建者：薛恒杰
	 * 工程名称：Marbles
	 * 创建时间：Aug 1, 2012 1:04:00 PM
	 * 类说明：MultiBilliard.as,
	 */
	import com.test.Ball;
	import com.utils.Collide;
	import com.utils.Physical;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent; 
	import flash.geom.Point;
	
	public class MultiBilliard extends Sprite {
		private var balls:Array;
		private var numBalls:uint = 10;
		private var bounce:Number = -1.0;
		private const acceleration:Number = -0.1;
		public function MultiBilliard() {
			addEventListener(Event.ADDED_TO_STAGE, addToStage);
		}
		private function addToStage(e:Event):void{
			init();
		}
		private function init():void {
			balls = new Array();
			for (var i:uint = 0; i < numBalls; i++) {
				var radius:Number = Math.random() * 10 + 10;
				var mass:Number = Math.pow(2, i) + 10;
				var ball:Ball = new Ball(radius, mass, 0xffffff - Math.pow(2, i))//mass);
				ball.x = (i + 1) * 40;
				ball.y = 250;
				ball.addEventListener(MouseEvent.CLICK, clickHandler);
				addChild(ball);
				balls.push(ball);
			}
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		private function clickHandler(e:MouseEvent):void{
			var ball:Ball = e.target as Ball;
			//			ball.vx = Math.random() * 50 + 5;
			//			ball.vy = Math.random() * 50 + 5;
			ball.c.speed = 4 + Math.random() * 5;
			ball.c.angle = Math.PI*Math.random();
		}
		private function onEnterFrame(event:Event):void {
			for (var i:uint = 0; i < numBalls; i++) {
				var ball:Ball = balls[i];
				var speed:Number = Math.sqrt(Math.pow(ball.vx, 2) + Math.pow(ball.vy, 2));
				speed += acceleration;
				ball.execution = ball.c.speed>0;
				if(ball.execution){
					//					var angle:Number = Math.atan2(ball.vy, ball.vx);
					//					ball.vx = speed * Math.cos(angle);
					//					ball.vy = speed * Math.sin(angle);
					//					ball.x += ball.vx;
					//					ball.y += ball.vy;
					//					checkWalls(ball);
					ball.vx = ball.c.speedx;
					ball.vy = ball.c.speedy;
					ball.x += ball.vx;
					ball.y += ball.vy;
					checkWalls(ball);
				}
			}
			for (i = 0; i < numBalls - 1; i++) {
				var ballA:Ball = balls[i];
				for (var j:Number = i + 1; j < numBalls; j++) {
					var ballB:Ball = balls[j];
					checkCollision(ballA, ballB);
				}
			}
		}
		private function checkWalls(ball:Ball):void {
			if (ball.x + ball.radius > stage.stageWidth) {
				ball.x = stage.stageWidth - ball.radius;
				//				ball.vx *= bounce;
				if (0 < ball.c.angle < Math.PI/2){
					ball.c.angle = Math.PI - ball.c.angle;
				}else{
					ball.c.angle -= 3*Math.PI - ball.c.angle;
				}
				//				if (3*Math.PI/2 < ball.c.angle < 2*Math.PI)ball.c.angle -= 3*Math.PI - ball.c.angle;
			} else if (ball.x - ball.radius < 0) {
				ball.x = ball.radius;
				//				ball.vx *= bounce;
				if (Math.PI < ball.c.angle < 3*Math.PI/2){
					ball.c.angle = 3*Math.PI - ball.c.angle;
				}else {
					ball.c.angle = Math.PI - ball.c.angle;
				}
				//				if (Math.PI/2 < ball.c.angle < Math.PI)ball.c.angle = Math.PI - ball.c.angle;
			}
			if (ball.y + ball.radius > stage.stageHeight) {
				ball.y = stage.stageHeight - ball.radius;
				//				ball.vy *= bounce;
				if (3*Math.PI/2 < ball.c.angle < 2*Math.PI){
					ball.c.angle = 2*Math.PI - ball.c.angle;
				}else{
					ball.c.angle = 2*Math.PI - ball.c.angle;
				}
				//				if (Math.PI < ball.c.angle < 3*Math.PI/2)ball.c.angle = 2*Math.PI - ball.c.angle;
			} else if (ball.y - ball.radius < 0) {
				ball.y = ball.radius;
				//				ball.vy *= bounce;
				if (3*Math.PI/2 < ball.c.angle < 2*Math.PI){
					ball.c.angle = 2*Math.PI - ball.c.angle;
				}else{
					ball.c.angle = Math.PI/2 + ball.c.angle;
				}
				//				if (Math.PI/2 < ball.c.angle < Math.PI)ball.c.angle = 2*Math.PI - ball.c.angle;
			}
		}
		private function checkCollision(ball0:Ball, ball1:Ball):void {
			if (!Physical.Circle2Hit(new Point(ball0.x, ball0.y), ball0.radius, new Point(ball1.x, ball1.y), ball1.radius))return
			
			var lB:Ball, rB:Ball;
			var mark:int;//1: b1在左侧 ;   2:b2在左侧;	3:垂直
			mark = ball0.x < ball1.x ? 1: (ball1.x < ball0.x ? 2 : 3);
			switch(mark){
				case 1:
					lB = ball0;
					rB = ball1;
					checkA(lB, rB);// 不垂直情况
					break;
				case 2:
					lB = ball1;
					rB = ball0;
					checkA(lB, rB);// 不垂直情况
					break;
				case 2:
					lB = ball0.y < ball1.y ? (ball0, rB = ball1) : (ball1, rB = ball0);
					checkB(lB, rB);//垂直
					break;
			}
		}//close function
		private function checkA(lB:Ball, rB:Ball):void{
			var angleLR:Number = Math.abs(Math.atan((rB.y - lB.y) / (rB.x - lB.x))); // 球中心连线和水平方向夹角,绝对
			//分两个园得中心连线的倾角是第一象限还是第四象限
			//分解速度到左半球坐标系
			var vxL:Number = 0,
				vyL:Number = 0,
				vxR:Number = 0,
				vyR:Number = 0;
			var isOne:Boolean = false;
			if (lB.y < rB.y){//第一象限
				vxL = lB.c.speed * Math.cos(lB.c.angle - angleLR);
				vyL = lB.c.speed * Math.sin(lB.c.angle - angleLR);
				
				vxR = rB.c.speed * Math.cos(rB.c.angle - angleLR);
				vyR = rB.c.speed * Math.sin(rB.c.angle - angleLR);
				isOne = true;
			}else{//第四象限 和 x正轴(angleLR = 0)
				vxL = lB.c.speed * Math.cos(lB.c.angle + angleLR);
				vyL = lB.c.speed * Math.sin(lB.c.angle + angleLR);
				
				vxR = rB.c.speed * Math.cos(rB.c.angle + angleLR);
				vyR = rB.c.speed * Math.sin(rB.c.angle + angleLR);
			}
			var c1:Collide = lB.c;
			var c2:Collide = rB.c;
			var vxL1:Number = ((c1.quality-c2.quality)*vxL+2*c2.quality*vxR)/(c1.quality+c2.quality);
			var vxR1:Number = ((c2.quality-c1.quality)*vxR+2*c1.quality*vxL)/(c1.quality+c2.quality);
			//以上求出在左半球坐标系里, 左球和右球的速度分别是
			//vxl1 vyl 和  vxr1 vyr
			//一下计算, 返回到原笛卡尔坐标系中的速度和角度
			lB.c.speed = Math.sqrt(vxL1 * vxL1 + vyL * vyL);
			rB.c.speed = Math.sqrt(vxR1 * vxR1 + vyR * vyR);
			
			var ang:Number = 0;
			if (vxL1 == 0){
				if (vyL > 0)ang = Math.PI / 2;
				if (vyL < 0)ang = Math.PI / -2;
			}else{
				ang = Math.atan2(vyL, vxL1);
				if (ang < 0)ang += 2 * Math.PI;
			}
			ang += isOne ? angleLR : -angleLR;//旋转坐标系到笛卡尔
			lB.c.angle = ang;
			if (vxR1 == 0){
				if (vyR > 0)ang = Math.PI / 2;
				if (vyR < 0)ang = Math.PI / -2;
			}else{
				ang = Math.atan2(vyR, vxR1);
				if (ang < 0)ang += 2 * Math.PI;
			}
			ang += isOne ? angleLR : -angleLR;//旋转坐标系到笛卡尔
			rB.c.angle = ang;
			trace(lB.c.speedx, rB.c.speedy, rB.c.speedx, rB.c.speedy);
		}
		private function checkB(lB:Ball, rB:Ball):void{
			var vxL:Number = 0,
				vyL:Number = lB.c.speed * Math.sin(lB.c.angle),
				vxR:Number = 0,
				vyR:Number = rB.c.speed * Math.sin(rB.c.angle);
			var vyL1:Number = ((lB.c.quality-rB.c.quality)*vxL+2*rB.c.quality*vxR)/(lB.c.quality+rB.c.quality);
			var vyR1:Number = ((rB.c.quality-lB.c.quality)*vxR+2*lB.c.quality*vxL)/(lB.c.quality+rB.c.quality);
			if (vyL1 > 0){
				lB.c.speed = vyL1;
				lB.c.angle = Math.PI/2;
			}else{
				lB.c.speed = -vyL1;
				lB.c.angle = 3*Math.PI/2;
			}
			if (vyR1 > 0){
				rB.c.speed = vyR1;
				rB.c.angle = Math.PI/2;
			}else{
				rB.c.speed = -vyR1;
				rB.c.angle = 3*Math.PI/2;
			}
		}//close function
		
		private function rotate(x:Number, y:Number,
								sin:Number, cos:Number, reverse:Boolean):Point {
			var result:Point = new Point();
			if (reverse) {
				result.x = x * cos + y * sin;
				result.y = y * cos - x * sin;
			} else {
				result.x = x * cos - y * sin;
				result.y = y * cos + x * sin;
			}
			return result;
		}
	}
}